home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
networking
/
ip
/
ka9q
/
src890906.arc
/
NRCMD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-08-19
|
24KB
|
1,018 lines
/* net/rom user command processing
* Copyright 1989 by Daniel M. Frank, W9NK. Permission granted for
* non-commercial distribution only.
*/
#include <stdio.h>
#include <ctype.h>
#include "global.h"
#include "mbuf.h"
#include "ax25.h"
#include "ax_mbx.h"
#include "netrom.h"
#include "nr4.h"
#include "timer.h"
#include "iface.h"
#include "lapb.h"
#include "cmdparse.h"
#include "session.h"
#include "socket.h"
#include "commands.h"
static int Nrsocket = -1;
struct ax25_addr Nr4user;
char *Nr4states[] = {
"Disconnected",
"Conn Pending",
"Connected",
"Disc Pending",
"Listening"
} ;
char *Nr4reasons[] = {
"Normal",
"By Peer",
"Timeout",
"Reset",
"Refused"
} ;
static int dobcnodes __ARGS((int argc,char *argv[],void *p));
static int dointerface __ARGS((int argc,char *argv[],void *p));
static int donfadd __ARGS((int argc,char *argv[],void *p));
static int donfdrop __ARGS((int argc,char *argv[],void *p));
static int donfdump __ARGS((void));
static int donfmode __ARGS((int argc,char *argv[],void *p));
static int donodefilter __ARGS((int argc,char *argv[],void *p));
static void donodetick __ARGS((void));
static int donodetimer __ARGS((int argc,char *argv[],void *p));
static int donracktime __ARGS((int argc,char *argv[],void *p));
static int donrchoketime __ARGS((int argc,char *argv[],void *p));
static int donrconnect __ARGS((int argc,char *argv[],void *p));
static int donrirtt __ARGS((int argc,char *argv[],void *p));
static int donrkick __ARGS((int argc,char *argv[],void *p));
static int dorouteadd __ARGS((int argc,char *argv[],void *p));
static int doroutedrop __ARGS((int argc,char *argv[],void *p));
static int doroutedump __ARGS((void));
static int dorouteinfo __ARGS((int argc,char *argv[],void *p));
static int donrqlimit __ARGS((int argc,char *argv[],void *p));
static int donrreset __ARGS((int argc,char *argv[],void *p));
static int donrretries __ARGS((int argc,char *argv[],void *p));
static int donrroute __ARGS((int argc,char *argv[],void *p));
static int donrstatus __ARGS((int argc,char *argv[],void *p));
static int donrttl __ARGS((int argc,char *argv[],void *p));
static int donruser __ARGS((int argc,char *argv[],void *p));
static int donrverbose __ARGS((int argc,char *argv[],void *p));
static int donrwindow __ARGS((int argc,char *argv[],void *p));
static void doobsotick __ARGS((void));
static int doobsotimer __ARGS((int argc,char *argv[],void *p));
static int putalias __ARGS((char *to, char *from,int complain));
static struct cmds Nrcmds[] = {
"acktime", donracktime, 0, 0, NULLCHAR,
"bcnodes", dobcnodes, 0, 2, "netrom bcnodes <interface>",
"connect", donrconnect, 1024, 2, "netrom connect <node>",
"choketime", donrchoketime, 0, 0, NULLCHAR,
"interface", dointerface, 0, 4,
"netrom interface <interface> <alias> <quality>",
"irtt", donrirtt, 0, 0, NULLCHAR,
"kick", donrkick, 0, 2, "netrom kick <&nrcb>",
"nodefilter", donodefilter, 0, 0, NULLCHAR,
"nodetimer", donodetimer, 0, 0, NULLCHAR,
"obsotimer", doobsotimer, 0, 0, NULLCHAR,
"qlimit", donrqlimit, 0, 0, NULLCHAR,
"reset", donrreset, 0, 2, "netrom reset <&nrcb>",
"retries", donrretries, 0, 0, NULLCHAR,
"route", donrroute, 0, 0, NULLCHAR,
"status", donrstatus, 0, 0, NULLCHAR,
"ttl", donrttl, 0, 0, NULLCHAR,
"user", donruser, 0, 0, NULLCHAR,
"verbose", donrverbose, 0, 0, NULLCHAR,
"window", donrwindow, 0, 0, NULLCHAR,
NULLCHAR,
} ;
static struct timer Nodetimer ; /* timer for nodes broadcasts */
static struct timer Obsotimer ; /* timer for aging routes */
/* Command multiplexer */
int
donetrom(argc,argv,p)
int argc ;
char *argv[] ;
void *p;
{
return subcmd(Nrcmds,argc,argv,p) ;
}
static struct cmds Routecmds[] = {
"add", dorouteadd, 0, 6,
"netrom route add <alias> <destination> <interface> <quality> <neighbor>",
"drop", doroutedrop, 0, 4,
"netrom route drop <destination> <neighbor> <interface>",
"info", dorouteinfo, 0, 2,
"netrom route info <destination>",
NULLCHAR,
} ;
/* Route command multiplexer */
static int
donrroute(argc, argv,p)
int argc ;
char *argv[] ;
void *p;
{
if (argc < 2) {
doroutedump() ;
return 0 ;
}
return subcmd(Routecmds,argc,argv,p) ;
}
/* Dump a list of known routes */
static int
doroutedump()
{
register struct nrroute_tab *rp ;
register int i, column ;
char buf[16] ;
char *cp ;
column = 1 ;
for (i = 0 ; i < NRNUMCHAINS ; i++)
for (rp = Nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rp->next) {
strcpy(buf,rp->alias) ;
/* remove trailing spaces */
if ((cp = strchr(buf,' ')) == NULLCHAR)
cp = &buf[strlen(buf)] ;
if (cp != buf) /* don't include colon for null alias */
*cp++ = ':' ;
pax25(cp,&rp->call) ;
printf("%-16s ",buf) ;
if (column++ == 4) {
printf("\n") ;
column = 1 ;
}
}
if (column != 1)
printf("\n") ;
return 0 ;
}
/* print detailed information on an individual route */
static int
dorouteinfo(argc,argv,p)
int argc ;
char *argv[] ;
void *p;
{
register struct nrroute_tab *rp ;
register struct nr_bind *bp ;
register struct nrnbr_tab *np ;
struct ax25_addr dest ;
char neighbor[60] ;
if (setcall(&dest,argv[1]) == -1) {
printf ("bad destination name\n") ;
return -1 ;
}
if ((rp = find_nrroute(&dest)) == NULLNRRTAB) {
printf("no such route\n") ;
return -1 ;
}
for (bp = rp->routes ; bp != NULLNRBIND ; bp = bp->next) {
np = bp->via ;
psax25(neighbor,np->call) ;
printf("%1s %3d %3d %-8s %s\n",
(bp->flags & NRB_PERMANENT ? "P" :
bp->flags & NRB_RECORDED ? "R" : " "),
bp->quality,bp->obsocnt,
Nrifaces[np->iface].iface->name,
neighbor) ;
}
return 0 ;
}
/* convert a null-terminated alias name to a blank-filled, upcased */
/* version. Return -1 on failure. */
static int
putalias(to,from,complain)
register char *to, *from ;
int complain ;
{
int len, i ;
if ((len = strlen(from)) > ALEN) {
if (complain)
printf ("alias too long - six characters max\n") ;
return -1 ;
}
for (i = 0 ; i < ALEN ; i++) {
if (i < len) {
if (islower(*from))
*to++ = toupper(*from++) ;
else
*to++ = *from++ ;
}
else
*to++ = ' ' ;
}
*to = '\0' ;
return 0 ;
}
/* Add a route */
static int
dorouteadd(argc, argv,p)
int argc ;
char *argv[] ;
void *p;
{
char alias[7] ;
struct ax25_addr dest ;
unsigned quality ;
char neighbor[AXALEN * 3] ;
register int i ;
int naddr ;
/* format alias (putalias prints error message if necessary) */
if (putalias(alias,argv[1],1) == -1)
return -1 ;
/* format destination callsign */
if (setcall(&dest,argv[2]) == -1) {
printf("bad destination callsign\n") ;
return -1 ;
}
/* find interface */
for (i = 0 ; i < Nr_numiface ; i++)
if (!strcmp(Nrifaces[i].iface->name,argv[3]))
break ;
if (i == Nr_numiface) {
printf("Interface \"%s\" not found\n",argv[3]) ;
return -1 ;
}
/* get and check quality value */
if ((quality = atoi(argv[4])) > 255) {
printf("maximum route quality is 255\n") ;
return -1 ;
}
/* Change from 871225 -- no digis in net/rom table */
naddr = argc - 5 ;
if (naddr > 1) {
printf("Use the ax25 route command to specify digipeaters\n") ;
return -1 ;
}
/* format neighbor address string */
setpath(neighbor,argv[5]) ;
return nr_routeadd(alias,&dest,i,quality,neighbor,1,0) ;
}
/* drop a route */
static int
doroutedrop(argc,argv,p)
int argc ;
char *argv[] ;
void *p;
{
struct ax25_addr dest, neighbor ;
register int i ;
/* format destination and neighbor callsigns */
if (setcall(&dest,argv[1]) == -1) {
printf("bad destination callsign\n") ;
return -1 ;
}
if (setcall(&neighbor,argv[2]) == -1) {
printf("bad neighbor callsign\n") ;
return -1 ;
}
/* find interface */
for (i = 0 ; i < Nr_numiface ; i++)
if (!strcmp(Nrifaces[i].iface->name,argv[3]))
break ;
if (i == Nr_numiface) {
printf("Interface \"%s\" not found\n",argv[3]) ;
return -1 ;
}
return nr_routedrop(&dest,&neighbor,i) ;
}
/* make an interface available to net/rom */
static int
dointerface(argc,argv,p)
int argc ;
char *argv[] ;
void *p;
{
int i ;
register struct iface *ifp ;
if (Nr_iface == NULLIF) {
printf("Attach netrom interface first\n") ;
return 1 ;
}
if (Nr_numiface >= NRNUMIFACE) {
printf("Only %d net/rom interfaces available\n",NRNUMIFACE) ;
return 1 ;
}
for(ifp=Ifaces;ifp != NULLIF;ifp = ifp->next){
if(strcmp(argv[1],ifp->name) == 0)
break;
}
if(ifp == NULLIF){
printf("Interface \"%s\" unknown\n",argv[1]);
return 1;
}
for (i = 0 ; i < Nr_numiface ; i++)
if (Nrifaces[i].iface == ifp) {
printf("Interface \"%s\" is already registered\n",argv[1]) ;
return 1 ;
}
Nrifaces[Nr_numiface].iface = ifp ;
if (putalias(Nrifaces[Nr_numiface].alias,argv[2],1) == -1)
return 1 ;
if ((Nrifaces[Nr_numiface].quality = atoi(argv[3])) > 255) {
printf("Quality cannot be greater than 255\n") ;
return 1 ;
}
Nr_numiface++ ; /* accept this interface */
return 0 ;
}
/* Broadcast nodes list on named interface. */
static int
dobcnodes(argc,argv,p)
int argc ;
char *argv[] ;
void *p;
{
register int i ;
for (i = 0 ; i < Nr_numiface ; i++)
if (!strcmp(Nrifaces[i].iface->name,argv[1]))
break ;
if (i == Nr_numiface) {
printf("Interface \"%s\" not found\n",argv[1]) ;
return 1 ;
}
nr_bcnodes(i) ;
return 0;
}
#define TICKSPERSEC (1000L / MSPTICK) /* Ticks per second */
/* Set outbound node broadcast interval */
static int
donodetimer(argc,argv,p)
int argc;
char *argv[];
void *p;
{
if(argc < 2){
printf("Nodetimer %lu/%lu seconds\n",(Nodetimer.start - Nodetimer.count)/TICKSPERSEC,
Nodetimer.start/TICKSPERSEC);
return 0;
}
stop_timer(&Nodetimer) ; /* in case it's already running */
Nodetimer.func = (void (*)())donodetick;/* what to call on timeout */
Nodetimer.arg = NULLCHAR; /* dummy value */
Nodetimer.start = atoi(argv[1])*TICKSPERSEC; /* set timer duration */
start_timer(&Nodetimer); /* and fire it up */
return 0;
}
static void
donodetick()
{
register int i ;
for (i = 0 ; i < Nr_numiface ; i++)
nr_bcnodes(i) ;
/* Restart timer */
start_timer(&Nodetimer) ;
}
/* Set timer for aging routes */
static int
doobsotimer(argc,argv,p)
int argc;
char *argv[];
void *p;
{
if(argc < 2){
printf("Obsotimer %lu/%lu seconds\n",(Obsotimer.start - Obsotimer.count)/TICKSPERSEC,
Obsotimer.start/TICKSPERSEC);
return 0;
}
stop_timer(&Obsotimer) ; /* just in case it's already running */
Obsotimer.func = (void (*)())doobsotick;/* what to call on timeout */
Obsotimer.arg = NULLCHAR; /* dummy value */
Obsotimer.start = atoi(argv[1])*TICKSPERSEC; /* set timer duration */
start_timer(&Obsotimer); /* and fire it up */
return 0;
}
/* Go through the routing table, reducing the obsolescence count of
* non-permanent routes, and purging them if the count reaches 0
*/
static void
doobsotick()
{
register struct nrnbr_tab *np ;
register struct nrroute_tab *rp, *rpnext ;
register struct nr_bind *bp, *bpnext ;
struct ax25_addr neighbor ;
int i ;
for (i = 0 ; i < NRNUMCHAINS ; i++) {
for (rp = Nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rpnext) {
rpnext = rp->next ; /* save in case we free this route */
for (bp = rp->routes ; bp != NULLNRBIND ; bp = bpnext) {
bpnext = bp->next ; /* in case we free this binding */
if (bp->flags & NRB_PERMANENT) /* don't age these */
continue ;
if (--bp->obsocnt == 0) { /* time's up! */
if (bp->next != NULLNRBIND)
bp->next->prev = bp->prev ;
if (bp->prev != NULLNRBIND)
bp->prev->next = bp->next ;
else
rp->routes = bp->next ;
rp->num_routes-- ; /* one less binding */
np = bp->via ; /* find the neighbor */
free(bp) ; /* now we can free the bind */
/* Check to see if we can free the neighbor */
if (--np->refcnt == 0) {
if (np->next != NULLNTAB)
np->next->prev = np->prev ;
if (np->prev != NULLNTAB)
np->prev->next = np->next ;
else {
memcpy(neighbor.call,np->call,ALEN) ;
neighbor.ssid = np->call[ALEN] ;
Nrnbr_tab[nrhash(&neighbor)] = np->next ;
}
free(np) ; /* free the storage */
}
}
}
if (rp->num_routes == 0) { /* did we free them all? */
if (rp->next != NULLNRRTAB)
rp->next->prev = rp->prev ;
if (rp->prev != NULLNRRTAB)
rp->prev->next = rp->next ;
else
Nrroute_tab[i] = rp->next ;
free(rp) ;
}
}
}
start_timer(&Obsotimer) ;
}
static struct cmds Nfcmds[] = {
"add", donfadd, 0, 3,
"netrom nodefilter add <neighbor> <interface>",
"drop", donfdrop, 0, 3,
"netrom nodefilter drop <neighbor> <interface>",
"mode", donfmode, 0, 0, NULLCHAR,
NULLCHAR, NULLFP, 0, 0,
"nodefilter subcommands: add drop mode",
} ;
/* nodefilter command multiplexer */
static int
donodefilter(argc,argv,p)
int argc ;
char *argv[] ;
void *p;
{
if (argc < 2) {
donfdump() ;
return 0 ;
}
return subcmd(Nfcmds,argc,argv,p) ;
}
/* display a list of <callsign,interface> pairs from the filter
* list.
*/
static int
donfdump()
{
int i, column = 1 ;
struct nrnf_tab *fp ;
char buf[16] ;
for (i = 0 ; i < NRNUMCHAINS ; i++)
for (fp = Nrnf_tab[i] ; fp != NULLNRNFTAB ; fp = fp->next) {
pax25(buf,&fp->neighbor) ;
printf("%-7s %-8s ",
buf,Nrifaces[fp->iface].iface->name) ;
if (column++ == 4) {
printf("\n") ;
column = 1 ;
}
}
if (column != 1)
printf("\n") ;
return 0 ;
}
/* add an entry to the filter table */
static int
donfadd(argc,argv,p)
int argc ;
char *argv[] ;
void *p;
{
struct ax25_addr neighbor ;
register int i ;
/* format callsign */
if (setcall(&neighbor,argv[1]) == -1) {
printf("bad neighbor callsign\n") ;
return -1 ;
}
/* find interface */
for (i = 0 ; i < Nr_numiface ; i++)
if (!strcmp(Nrifaces[i].iface->name,argv[2]))
break ;
if (i == Nr_numiface) {
printf("Interface \"%s\" not found\n",argv[2]) ;
return -1 ;
}
return nr_nfadd(&neighbor,i) ;
}
/* drop an entry from the filter table */
static int
donfdrop(argc,argv,p)
int argc ;
char *argv[] ;
void *p;
{
struct ax25_addr neighbor ;
register int i ;
/* format neighbor callsign */
if (setcall(&neighbor,argv[1]) == -1) {
printf("bad neighbor callsign\n") ;
return -1 ;
}
/* find interface */
for (i = 0 ; i < Nr_numiface ; i++)
if (!strcmp(Nrifaces[i].iface->name,argv[2]))
break ;
if (i == Nr_numiface) {
printf("Interface \"%s\" not found\n",argv[2]) ;
return -1 ;
}
return nr_nfdrop(&neighbor,i) ;
}
/* nodefilter mode subcommand */
static int
donfmode(argc,argv,p)
int argc ;
char *argv[] ;
void *p;
{
if (argc < 2) {
printf("filter mode is ") ;
switch (Nr_nfmode) {
case NRNF_NOFILTER:
printf("none\n") ;
break ;
case NRNF_ACCEPT:
printf("accept\n") ;
break ;
case NRNF_REJECT:
printf("reject\n") ;
break ;
default:
printf("some strange, unknown value\n") ;
}
return 0 ;
}
switch (argv[1][0]) {
case 'n':
case 'N':
Nr_nfmode = NRNF_NOFILTER ;
break ;
case 'a':
case 'A':
Nr_nfmode = NRNF_ACCEPT ;
break ;
case 'r':
case 'R':
Nr_nfmode = NRNF_REJECT ;
break ;
default:
printf("modes are: none accept reject\n") ;
return -1 ;
}
return 0 ;
}
/* netrom network packet time-to-live initializer */
static int
donrttl(argc, argv,p)
int argc ;
char *argv[] ;
void *p;
{
return setshort(&Nr_ttl,"Time to live",argc,argv);
}
/* verbose route broadcast */
static int
donrverbose(argc,argv,p)
int argc ;
char *argv[] ;
void *p;
{
return setbool(&Nr_verbose,"Verbose flag",argc,argv);
}
/* Initiate a NET/ROM transport connection */
static int
donrconnect(argc,argv,p)
int argc ;
char *argv[] ;
void *p;
{
struct ax25_addr *np ;
struct sockaddr_nr lsocket, fsocket;
char alias[10];
struct session *sp;
/* Get a session descriptor */
if ((sp = newsession(argv[1],NRSESSION)) == NULLSESSION) {
printf("Too many sessions\n") ;
freeargs(argc,argv);
return 1 ;
}
if((sp->s = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1){
freesession(sp);
printf("Can't create socket\n");
freeargs(argc,argv);
return 1;
}
lsocket.nr_family = AF_NETROM;
/* Set up our local username, bind would use Mycall instead */
memcpy(lsocket.nr_addr.user_call,&Nr4user,AXALEN);
/* Putting anything else than Mycall here will not work */
memcpy(lsocket.nr_addr.node_call,&Mycall,AXALEN);
bind(sp->s,(char *)&lsocket,sizeof(struct sockaddr_nr));
/* See if the requested destination could be an alias, and */
/* find and use it if it is. Otherwise assume it is an ax.25 */
/* address. */
if (putalias(alias,argv[1],0) != -1 &&
(np = find_nralias(alias)) != NULLAXADDR) {
memcpy(fsocket.nr_addr.user_call,np,AXALEN) ;
memcpy(fsocket.nr_addr.node_call,np,AXALEN) ;
}
else { /* parse ax25 callsign */
/* Only the user callsign of the remote station is never used by */
/* NET/ROM, but it is needed for the psocket() call. */
setcall((struct ax25_addr *)fsocket.nr_addr.user_call,argv[1]);
setcall((struct ax25_addr *)fsocket.nr_addr.node_call,argv[1]);
}
freeargs(argc,argv);
fsocket.nr_family = AF_NETROM;
pax25(alias,(struct ax25_addr *)fsocket.nr_addr.node_call);
printf("Trying %s...\n",alias);
return axnrconnect(sp, (char *)&fsocket, sizeof(struct sockaddr_nr));
}
int
nr4start(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int s;
freeargs(argc,argv);
if (Nrsocket != -1)
return -1;
psignal(Curproc,0); /* Don't keep the parser waiting */
chname(Curproc,"NETROM listener");
Nrsocket = socket(AF_NETROM,SOCK_SEQPACKET,0);
/* bind() is done automatically */
if (listen(Nrsocket,1) == -1) {
close_s(Nrsocket);
Nrsocket = -1;
return -1;
}
for(;;){
if((s = accept(Nrsocket,NULLCHAR,NULLINT)) == -1)
break; /* Service is shutting down */
if (Ax25mbox)
newproc("mbox",2048,mbx_incom,s,(void *)NRSESSION,NULL);
else
newproc("in_ax25",2048,axnrhandle,s,(void *)NRSESSION,NULL);
}
close_s(Nrsocket);
Nrsocket = -1;
return 0;
}
int
nr40(argc,argv,p)
int argc;
char *argv[];
void *p;
{
close_s(Nrsocket);
Nrsocket = -1;
return 0;
}
/* Reset a net/rom connection abruptly */
static int
donrreset(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct nr4cb *cb ;
extern char Notval[];
cb = (struct nr4cb *)htol(argv[1]);
if(!nr4valcb(cb)){
printf(Notval);
return 1;
}
reset_nr4(cb);
return 0;
}
/* Force retransmission on a net/rom connection */
static int
donrkick(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct nr4cb *cb ;
extern char Notval[];
cb = (struct nr4cb *)htol(argv[1]);
if (kick_nr4(cb) == -1) {
printf(Notval);
return 1;
} else
return 0;
}
/* netrom transport ACK delay timer */
static int
donracktime(argc, argv,p)
int argc ;
char *argv[] ;
void *p;
{
return setlong(&Nr4acktime,"Ack delay time (ms)",argc,argv);
}
/* netrom transport choke timeout */
static int
donrchoketime(argc, argv,p)
int argc ;
char *argv[] ;
void *p;
{
return setlong(&Nr4choketime,"Choke timeout (ms)",argc,argv);
}
/* netrom transport initial round trip time */
static int
donrirtt(argc, argv,p)
int argc ;
char *argv[] ;
void *p;
{
return setlong(&Nr4irtt,"Initial RTT (ms)",argc,argv);
}
/* netrom transport receive queue length limit. This is the */
/* threshhold at which we will CHOKE the sender. */
static int
donrqlimit(argc, argv,p)
int argc ;
char *argv[] ;
void *p;
{
return setshort(&Nr4qlimit,"Queue limit (bytes)",argc,argv);
}
/* Display or change our NET/ROM username */
static int
donruser(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char buf[15];
if(argc < 2){
pax25(buf,&Nr4user);
printf("%s\n",buf);
return 0;
}
if(setcall(&Nr4user,argv[1]) == -1)
return -1;
Nr4user.ssid |= E;
return 0;
}
/* netrom transport maximum window. This is the largest send and */
/* receive window we may negotiate */
static int
donrwindow(argc, argv,p)
int argc ;
char *argv[] ;
void *p;
{
return setshort(&Nr4window,"Window (frames)",argc,argv);
}
/* netrom transport maximum retries. This is used in connect and */
/* disconnect attempts; I haven't decided what to do about actual */
/* data retries yet. */
static int
donrretries(argc, argv,p)
int argc ;
char *argv[] ;
void *p;
{
return setshort(&Nr4retries,"Retry limit",argc,argv);
}
/* Display the status of NET/ROM connections */
static int
donrstatus(argc, argv,p)
int argc ;
char *argv[] ;
void *p;
{
int i ;
struct nr4cb *cb ;
char luser[10], ruser[10], node[10] ;
extern char Notval[] ;
if (argc < 2) {
printf(" &CB Snd-W Snd-Q Rcv-Q LUser RUser @Node State\n");
for (i = 0 ; i < NR4MAXCIRC ; i++) {
if ((cb = Nr4circuits[i].ccb) == NULLNR4CB)
continue ;
pax25(luser,(struct ax25_addr *)cb->local.user_call) ;
pax25(ruser,(struct ax25_addr *)cb->remote.user_call) ;
pax25(node,(struct ax25_addr *)cb->remote.node_call) ;
printf("%8lx %3d %5d %5d %9s %9s %-9s %s\n",
ptol(cb), cb->nbuffered, len_q(cb->txq),
len_mbuf(cb->rxq), luser, ruser, node,
Nr4states[cb->state]) ;
}
return 0 ;
}
cb = (struct nr4cb *)htol(argv[1]) ;
if (!nr4valcb(cb)) {
printf(Notval) ;
return 1 ;
}
donrdump(cb) ;
return 0 ;
}
/* Dump one control block */
void
donrdump(cb)
struct nr4cb *cb ;
{
char luser[10], ruser[10], node[10] ;
unsigned seq ;
struct nr4txbuf *b ;
struct timer *t ;
pax25(luser,(struct ax25_addr *)cb->local.user_call) ;
pax25(ruser,(struct ax25_addr *)cb->remote.user_call) ;
pax25(node,(struct ax25_addr *)cb->remote.node_call) ;
printf("Local: %s %d/%d Remote: %s @ %s %d/%d State: %s\n",
luser, cb->mynum, cb->myid, ruser, node,
cb->yournum, cb->yourid, Nr4states[cb->state]) ;
printf("Window: %-5u Rxpect: %-5u RxNext: %-5u RxQ: %-5d %s\n",
cb->window, uchar(cb->rxpected), uchar(cb->rxpastwin),
len_mbuf(cb->rxq), cb->qfull ? "RxCHOKED" : "") ;
printf(" Unack: %-5u Txpect: %-5u TxNext: %-5u TxQ: %-5d %s\n",
cb->nbuffered, uchar(cb->ackxpected), uchar(cb->nextosend),
len_q(cb->txq), cb->choked ? "TxCHOKED" : "") ;
printf("TACK: ") ;
if (run_timer(&cb->tack))
printf("%lu", (cb->tack.start - cb->tack.count) * MSPTICK) ;
else
printf("stop") ;
printf("/%lu ms; ", cb->tack.start * MSPTICK) ;
printf("TChoke: ") ;
if (run_timer(&cb->tchoke))
printf("%lu", (cb->tchoke.start - cb->tchoke.count) * MSPTICK) ;
else
printf("stop") ;
printf("/%lu ms; ", cb->tchoke.start * MSPTICK) ;
printf("TCD: ") ;
if (run_timer(&cb->tcd))
printf("%lu", (cb->tcd.start - cb->tcd.count) * MSPTICK) ;
else
printf("stop") ;
printf("/%lu ms", cb->tcd.start * MSPTICK) ;
if (run_timer(&cb->tcd))
printf("; Tries: %u\n", cb->cdtries) ;
else
printf("\n") ;
printf("Backoff Level %u SRTT %ld ms Mean dev %ld ms\n",
cb->blevel, cb->srtt, cb->mdev) ;
/* If we are connected and the send window is open, display */
/* the status of all the buffers and their timers */
if (cb->state == NR4STCON && cb->nextosend != cb->ackxpected) {
printf("TxBuffers: Seq Size Tries Timer\n") ;
for (seq = cb->ackxpected ;
nr4between(cb->ackxpected, seq, cb->nextosend) ;
seq = (seq + 1) & NR4SEQMASK) {
b = &cb->txbufs[seq % cb->window] ;
t = &b->tretry ;
printf(" %3u %3d %5d %lu/%lu\n",
seq, len_mbuf(b->data), b->retries + 1,
(t->start - t->count) * MSPTICK, t->start * MSPTICK) ;
}
}
}